﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Linq;
using Styx;
using Styx.Helpers;
using Styx.Pathing;
using Styx.CommonBot.Inventory;
using Styx.CommonBot.Profiles;
using Styx.CommonBot.Routines;
using Styx.Pathing;
using Styx.CommonBot.Frames;
using Styx.CommonBot.POI;
using Styx.CommonBot;
using Styx.Common;
using Styx.Common.Helpers;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals.World;
using System.Windows.Forms;
using Tripper.Navigation;

namespace DoABarrelRoll
{
    public partial class DoABarrelRoll
    {
        private bool LOSCheck = false;
        private bool MadeItToOrg = false;
        private bool DidRepair = false;
        private bool CheckRunes = false;
        private bool MovedOutside = false;
        private bool DidMail = false;
        private bool MovedToPortals = false;
        private bool UsedPortal = false;
        private bool ReturnedToXYZ = false;
        private bool IsStarted = false;
        private bool IsFinished = false;
        private WoWPoint OldLocation;
        private uint OldMapId;
        private string OldZoneName;
        private BotPoi CurrentPOI { get { return BotPoi.Current; } }
        private List<string> BadBotBases = new List<string> { "Instancebuddy", "PartyBot", "LazyRaider", "BG Bot [Beta]", "PvP", "Mixed Mode" };

        private bool LockItUp(string method, List<WoWUnit> objList)
        {
            ObjectManager.Update();
            bool _Return = false;
            if (method == "moreMobs")
            {
                /*Checks for mobs within 15 yards of the loot we want to roll to... This way you won't be rolling into an agro field*/
                foreach (WoWUnit z in objList)
                {
                    if (z.IsValid && !z.IsMe && z.Guid != LastPOI.Guid && z.Location.Distance(LastPOI.Location) <= 15 && !z.IsDead && z.IsHostile) { _Return = true; }
                }
                if (_Return) { /*Log("Found Hostiles near", LastPOI.Name);*/ }
                return _Return;
            }
            if (method == "closerLoot")
            {
                /*Check is there is closer what our POI is...  The bot is sometimes stupid, and could possibly set a POI different than what it is actually moving to loot
                 * This would result in rolling to the wrong loot*/
                foreach (WoWUnit z in objList)
                {
                    if (z.IsValid && !z.IsMe && z.Guid != LastPOI.Guid && z.Lootable && z.Location.Distance(Me.Location) < LastPOI.Location.Distance(Me.Location)) { _Return = true; }
                }
                if (_Return) { /*Log("Found Loot closer than", LastPOI.Name);*/ }
                return _Return;
            }
            return true;
        }

        private bool IsLastPOItheCurrentPOI()
        {
            if (LastPOI.Guid == CurrentPOI.Guid) return true;
            else return false;
        }

        private bool RollOnlyWithPerfection()
        {
            while (Navigator.GeneratePath(Me.Location, LastPOI.Location).Length > 2) { LOSCheck = true; Navigator.MoveTo(LastPOI.Location); Thread.Sleep(ranNum(250, 500)); }
            if (LOSCheck) { Log("Moved into LOS/1 CTM left to: ", LastPOI.Name); }
            return LOSCheck;
        }

        private void RollToPOI()
        {
            if (UseRoll && BotPoi.Current.Type == PoiType.Kill && BotPoi.Current.Location.Distance(Me.Location) > 25 && !Me.Mounted)
            {
                //Roll towards Poi's we need to kill, if over 25 yards away and not mounted
                if (SpellManager.CanCast("Roll"))
                { BotPoi.Current.AsObject.ToUnit().Face(); StyxWoW.SleepForLagDuration(); SpellManager.Cast("Roll"); Log("Rolled towards: ", BotPoi.Current.Name); WoWMovement.ClickToMove(BotPoi.Current.Location); }

            }
            if (Me.CurrentTarget == null && UseRoll && Styx.Helpers.CharacterSettings.Instance.LootMobs.Equals(true))
            {

                if (BotPoi.Current != null && CurrentPOI.AsObject is WoWUnit)
                {
                    LastPOI = CurrentPOI.AsObject;//Sets the GUID of the Current/Last POI

                    if (true)
                    {
                        bool closerLoot = false;
                        bool moreMobs = false;
                        LOSCheck = false;
                        ObjectManager.Update();

                        List<WoWUnit> objList = ObjectManager.GetObjectsOfType<WoWUnit>()
                        .Where(o => !o.IsDead)
                        .OrderBy(o => o.Distance).ToList();

                        moreMobs = LockItUp("moreMobs", objList);


                        closerLoot = LockItUp("closerLoot", objList);

                        if (LastPOI.ToUnit().Lootable && SpellManager.CanCast("Roll") && LastPOI.Distance >= 19 && LastPOI.Distance <= 40 && !moreMobs && !closerLoot)
                        {
                            //Log("Checking LOS", null);
                            /*if (!LastPOI.InLineOfSight) { bool done = false; Log("Moving into LoS", null); LOSCheck = true; while (!done) { Navigator.MoveTo(LastPOI.Location); Thread.Sleep(ranNum(750, 1000)); if (LastPOI.InLineOfSight) { done = true; } } }*/

                            RollOnlyWithPerfection();

                            if (!Me.Mounted)
                            {
                                if (LOSCheck == true && SpellManager.CanCast("Roll") && LastPOI.Distance >= 19 && LastPOI.Distance <= 50)
                                { LastPOI.ToUnit().Face(); StyxWoW.SleepForLagDuration(); SpellManager.Cast("Roll"); Log("Rolled(LoS) to", LastPOI.Name); Navigator.Clear(); Navigator.MoveTo(LastPOI.Location); }

                                if (LOSCheck == false)
                                { LastPOI.ToUnit().Face(); StyxWoW.SleepForLagDuration(); SpellManager.Cast("Roll"); Log("Rolled(N-LoS) to", LastPOI.Name); Navigator.Clear(); Navigator.MoveTo(LastPOI.Location); }
                                LOSCheck = false;
                                checkedMobs = false;
                            }
                            else
                            {
                                Log("I am mounted. Not Rolling to: ", LastPOI.Name);
                            }
                        }
                    }
                }
            }
        }
    }
}
